package com.tianquan.test.redisAop;/**
 * @author starsea
 * @date 2024-10-08 上午10:29
 */

import com.tianquan.miracle.annotation.Autowired;
import com.tianquan.miracle.aop.annotation.Around;
import com.tianquan.miracle.aop.JoinPoint;
import com.tianquan.miracle.aop.annotation.Pointcut;
import org.redisson.api.RedissonClient;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * @BelongsProject: uploaddemo
 * @BelongsPackage: com.tianquan.miracledemo.test
 * @Author: tianquan
 * @CreateTime: 2024-10-08  10:29
 * @Description: 用自己实现的aop实现@cache
 * @Version: 1.0
 */
// @Aspect
// @Component
public class RedisAop {

    @Autowired
    private RedissonClient redissonClient;

    @Pointcut(annotation = {Cache.class})
    public void test() {
    }

    @Around("test()")
    public Object around(JoinPoint joinPoint) throws Throwable {
        Method method = joinPoint.getMethod();
        Cache cache = method.getAnnotation(Cache.class);
        String key = cache.key();
        // 解析key
        key = parserKey(key, method, joinPoint.getArgs());
        String keyName = cache.prefix() + ":" + key;
        // 查询缓存
        Object object = redissonClient.getBucket(keyName).get();
        // 缓存中存在就直接返回
        if (object != null) return object;
        // 缓存中不存在,执行方法,拿到数据
        object = joinPoint.proceed(joinPoint.getArgs());
        // 将数据存入缓存
        boolean expire = cache.isExpire();
        if (expire) {
            redissonClient.getBucket(keyName).set(object, cache.time(), cache.unit());
        } else redissonClient.getBucket(keyName).set(object);
        return object;
    }

    private String parserKey(String key, Method method, Object[] args) throws Exception {
        // 不需要解析
        if (key == null || !key.contains("#")) return key;
        key = key.replace("#", "");
        Parameter[] parameters = method.getParameters();
        if (key.contains(".")) {
            String[] keys = key.split("\\.");
            if (keys.length > 2) throw new RuntimeException("The key format is incorrect " + key);
            String objectName = keys[0];
            String objectFieldName = keys[1];
            Object object = null;
            // 从参数中找到该对象
            for (int i = 0; i < parameters.length; i++) {
                Parameter parameter = parameters[i];
                if (parameter.getName().equals(objectName))
                    object = args[i];
            }
            if (object == null) throw new RuntimeException("Object not found name is " + objectName);
            Class<?> aClass = object.getClass();
            // 获取get方法
            Method getMethod = aClass.getMethod("get" + objectFieldName.substring(0, 1).toUpperCase() +
                    objectFieldName.substring(1));
            key = getMethod.invoke(object).toString();
            return key;
        }
        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            if (parameter.getName().equals(key))
                key = args[i].toString();
        }
        return key;
    }


}
